package pers.ree.demo.inner;

/**
 * 局部内部类
 */
public class OuterClass {

    private int num;

    private final int NUM = 1;

    public int publicNum;

    public final int PUBLIC_NUM = 1;


    public void outerMethod() {
        final int finalVar = 10; // 常量，不可修改
        int modifiableVar = 20; // 变量，但是在方法中未被修改，即effectively final（名义上是变量，实际上的final）

        // 局部内部类只能在定义它的方法内可见和使用，所以不能加public, static, final等修饰
        class LocalInnerClass {
            // 无论这个构造方法是不是private，都能且只能在outerMethod及其其他局部内部类中使用
//            private LocalInnerClass() {
//
//            }

            private String str = "LocalInnerClassPrivateStr";

            protected String protectedStr = "LocalInnerClassProtectedStr";

            private final int a = 1;

            public int b = 2;

            private void accessAndModify() {
                /** 访问方法内的局部常量与变量 begin */
                // 可以访问 final 变量，但不可修改
                System.out.println(finalVar);

                // 可以访问未被修改的变量
                System.out.println(modifiableVar);
                // 这句注释如果放开，上面一句中的modifiableVar会报错，因为局部内部类中只能访问final或者effectively final的变量
//                modifiableVar += 5;
                /** 访问方法内的局部常量与变量 end */

                /** 访问实例变量与常量 begin */
                // 访问实例变量
                num += 1; // 访问私有的实例变量
                publicNum += 1;

                // 访问实例的常量
                System.out.println(NUM);
                System.out.println(PUBLIC_NUM);
                /** 访问实例变量与常量 end */
            }
        }

        // 局部内部类也可以继承
        class ChildLocalInnerClass extends LocalInnerClass {
            void exec() {
                // 子类可以访问
                super.accessAndModify();

                System.out.println(super.protectedStr);
                System.out.println(super.str);
            }
        }

        class OtherLocalInnerClass {
            private void privatMethod() {
                LocalInnerClass localInnerClass = new LocalInnerClass();
                System.out.println("在同个方法的其他内部类中直接访问局部内部类LocalInnerClass的私有成员变量str="+localInnerClass.str);
                System.out.println("在同个方法的其他内部类中直接访问局部内部类LocalInnerClass的私有成员常量a="+localInnerClass.a);
            }
        }

        LocalInnerClass innerObject = new LocalInnerClass();
        innerObject.accessAndModify();
        // 让外部方法通过打印语句观察到修改后的结果
        System.out.println("Modified variable: " + modifiableVar);

        // 定义局部内部类的方法中以及该方法中的其他内部类或局部内部类的子类都可以访问局部内部类的方法和变量、常量
        // todo 所以局部内部类中的private等访问控制符似乎除了可读性外没有其他作用
        System.out.println(innerObject.protectedStr);
        System.out.println(innerObject.str);
        System.out.println(innerObject.a); // private的常量

        ChildLocalInnerClass childLocalInnerObj = new ChildLocalInnerClass();
        childLocalInnerObj.exec();
    }

    public void test() {
        outerMethod(); // 只能访问outerMethod方法，但是无法访问其中的内部类LocalInnerClass
//        LocalInnerClass localInnerClass = new LocalInnerClass();
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.outerMethod();
    }
}
